Skip to content

Conversation

@anwang2009
Copy link

Description of Proposal

We'd like to propose more structured categorization of SdrShaderNodes for clarity, discoverability, and transferability between DCCs.

Link to Rendered Proposal

@anwang2009 anwang2009 changed the title Sdr categorization SdrShaderNode categorization Oct 23, 2025
@jesschimein jesschimein moved this from Draft to Finalizing in OpenUSD Proposals Status Oct 23, 2025
@JamesPedFoundry
Copy link

Shader Terminals

There is one piece of information I see missing here which is crucial for shading, and that is how these shaders link up to the RenderDelegates and Material Terminal namespaces.

Typically the render delegates specify the materialContext's they support (mtlx, prman, arnold, nsi, glslfx), and thus which terminals they are interested in, with a specified order. However, currently, and in the proposal, there is no link on the shader as to which terminal namespaces are expected (not enforced).

To me, this makes sense(if sticking with the current terms) as the "target". Currently the proposal describes MaterialX specifying its target as "MaterialX". I would like to suggest that becomes mtlx, and similarly prman, arnold, nsi, glsfx etc...

This does cause some confusion for UsdPreviewSurface in particular; which tends to be supported by all. Typically defined with a terminal namespace/materialContext of glslfx or no target at all. I guess here UsdPreviewSurface could be specified with no target, and thus would appear relevant for all.

It may be that we don't try to shoehorn this into "targets" and have a separate "preferredMaterialContext" or similar field which describes the preferred terminal namespace to have it understood by a renderer as a priority.

Collections

I am also interested to learn more about "collections", the single sentence not quite fully describing their behaviours/design ideas? Is this how a renderer would specify which shaders should appear to an artist when they want to see shaders related to their renderer?

Registry method request

Additionally it would make me happy if there are methods added to the SdrRegistry to "getAllBySubDomain(const TfToken subDomain)" which could then filter (and likely cached for performance reasons) all the shaders related to a certain context; since I imagine this being used frequently to populate user interfaces. (We can then group further by "target")

API changes

I am also not super keen on the change in behaviour for GetShaderNodeIdentifiers/GetShadeNodeNames. We typically use this to get all the shaders and it works well for returning us a list of all the shaders without filtering applied. These method names make sense for their action, and with the new proposal for family to be more utilised, I see this being cumbersome to have to request all the possible different families of shaders/lights? I may well be misunderstanding the change, but from our usage, we use these methods to get all the shaders, and then we loop through thouse shaders and look at the actual shader items in the registry and retain the ones we care about.
For a more concrete example (In pseudo code), we can:

GetLights():
lights = {}
 for shader in GetShaderNodeIdentifiers():
    if shader.getContext() == "light":  
      lights[shaderName] = shader

If anything I'd prefer the removal of the optional filter altogether from GetShaderNodeIdentifiers, and retaining the more specialised method of GetShaderNodesByFamily if filtering by Family is necessary.

@anwang2009
Copy link
Author

anwang2009 commented Nov 7, 2025

Hey @JamesPedFoundry , thanks for the feedback!

Re: Shader Terminals

Reconsidering target in context of terminal namespaces is a great point, and I've been exploring this more. The rabbit hole goes pretty deep -- this is far from final but here's what we're thinking so far:

Here are the concepts at play.

  • source container is the raw shading asset's form that gets consumed, often associated with some file format.
  • target system is something like MaterialX, OSL, glslfx that usually has its own standard and shading language
  • target renderer is a renderer like Renderman or Arnold that often has support for multiple shading systems
  • terminal namespace is a convention adopted by USD where shaders that are terminal nodes in a network define properties with names of the form “outputs:namespace:propName”. Render delegates in Hydra use this convention to find specific terminal properties in priority order of renderContexts as terminal namespaces. Hydra render delegates can also use renderContext as non-terminal namespaces.

It's becoming clear to me that target as a term is not constrained enough, so we're re-evaluating the term itself as well as its semantics relative to the above concepts.

  • target renderer isn't a useful item to have on every node, since it's better for the "source of truth" as to whether a node is renderable be centralized to the renderer itself, to minimize updates to shader definitions and code when the renderer changes what shading ecosystems it supports. If two different renderers have support for the same OSL node, it would be tragic to have to register two different nodes in Sdr, one for each renderer. So the best use for target renderer seems to be to exclude nodes from consideration with other renderers.

We're also re-evaluating sourceType, as currently it sounds like source container, but the term target system may be more accurate to the node's consumers (this is subject to change, I'm still spelunking through codebases).

More thoughts soon to come on this.

Re: Collections

Collections aren't meant to be renderer-based -- you could use them to specify renderers but I think "renderer" deserves more first-class treatment as discussed above.

  • Collections are meant to be more generic -- they should be specified at node parse time, populated through Sdr parser plugins. Metadata on shader definitions themselves might need to be modified to specify what collections they belong to, or one might programmatically deduce what collections a node should belong to in the parser plugin itself.
  • This is intended to enable categorizations of nodes that wouldn't fit in the proposed structured hierarchy or existing metadata. Perhaps usd's "previewSurface"-related nodes would be grouped into a "UsdPreview" collection. Maybe you'd want to categorize your shaders in terms of computational heaviness, like "perfLight" or "perfHeavy" -- something like that.

Re: Registry method request

We recently landed a SdrShaderNode Query API. An additional CustomFilter method is in the works that takes a custom function with signature bool (SdrShaderNode) so folks can provide their own filters. For now, no caching. I'm also planning a utility function to help with displaying nested groupings of nodes, motivated largely by one of the asks in this issue you filed. This query API isn't as convenient as getAllBySubDomain would be, but should be more flexible.

Re: API changes

If anything I'd prefer the removal of the optional filter altogether from GetShaderNodeIdentifiers, and retaining the more specialised method of GetShaderNodesByFamily if filtering by Family is necessary.

Thanks for the usage example.

  • Now I'm leaning towards just leaving GetShaderNodeIdentifiers and GetShaderNodeNames alone, since they'd be the only registry methods that allowing filtering on family before nodes are parsed.
  • The behavior of GetShaderNodesByFamily is covered by the query API addition and the proposed SdrShaderNodePtrVec ParseAndGetAll() registry addition. I don't think that getting all the nodes for a specific family is a popular operation, so I'd deprecate it in favor of the alternate suggestions, but I could be wrong. The safest alternative is to just let GetShaderNodesByFamily exist as convenience API but require it to specify a concrete family. The latter's fair and I'll prefer it since there's more contentious items otherwise in the proposal :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Finalizing

Development

Successfully merging this pull request may close these issues.

2 participants